package com.llb666.shop.user.api.controller.center;

import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson2.JSON;
import com.llb666.common.core.constant.AppConstants;
import com.llb666.common.core.utils.cookie.CookieUtils;
import com.llb666.common.core.web.response.BaseResponse;
import com.llb666.common.core.web.response.DataResponse;
import com.llb666.common.redis.service.RedisService;
import com.llb666.shop.user.api.dto.center.CenterUserDto;
import com.llb666.shop.user.api.vo.UsersVo;
import com.llb666.shop.user.domain.entity.Users;
import com.llb666.shop.user.domain.service.center.CenterUserService;
import com.llb666.shop.user.infracore.config.FileUploadConfig;
import com.qcloud.cos.COSClient;
import com.qcloud.cos.model.ObjectMetadata;
import com.qcloud.cos.model.PutObjectRequest;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
import java.io.InputStream;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;

/**
 * 用户信息接口.
 *
 * @author llb666
 * @version 1.0
 */
@Tag(name = "用户信息接口")
@RestController
@RequestMapping("userInfo")
@Slf4j
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
public class CenterUserController {

    private final CenterUserService userService;
    private final FileUploadConfig fileUpload;
    private final COSClient cosClient;
    private final RedisService redisService;

    @Operation(summary = "修改用户信息")
    @PostMapping("update")
    public BaseResponse update(
            @Parameter(name = "userId", description = "用户ID", required = true) @RequestParam String userId,
            @Parameter(name = "userBo", description = "用户修改表单信息", required = true) @RequestBody @Valid CenterUserDto userDto,
            HttpServletRequest request,
            HttpServletResponse response,
            BindingResult bindingResult) {

        if (bindingResult.hasErrors()) {
            Map<String, String> errors = getErrors(bindingResult);
            return DataResponse.errorMap(errors);
        }
        Users user = userService.updateUserInfo(userId, CenterUserDto.Converter.INSTANCE.dto2do(userDto));
        setNullProperty(user);
        String userStrCookie = CookieUtils.getCookieValue(request, "user", true);
        UsersVo usersVoToken = JSON.parseObject(userStrCookie, UsersVo.class);
        UsersVo usersVo = UsersVo.Converter.INSTANCE.do2Vo(user);
        assert usersVoToken != null;
        usersVo.setUserUniqueToken(usersVoToken.getUserUniqueToken());
        CookieUtils.setCookie(request, response, "user", JSONObject.toJSONString(usersVo), true);
        return BaseResponse.ok();
    }

    @Operation(summary = "上传头像")
    @PostMapping("uploadFace")
    public BaseResponse uploadFace(
            @Parameter(name = "userId", description = "用户ID", required = true) @RequestParam String userId,
            @Parameter(name = "file", description = "用户头像", required = true) MultipartFile file,
            HttpServletRequest request, HttpServletResponse response) throws Exception {
        //Cos分布式文件系统上传.
        String path = "";
        if (file != null) {
            //获取文件名称
            String filename = file.getOriginalFilename();
            if (StringUtils.isNotBlank(filename)) {
                //分割出文件名，获取后缀名.
                String[] fileNameArr = filename.split("\\.");
                String suffix = fileNameArr[fileNameArr.length - 1];
                if (!"png".equalsIgnoreCase(suffix) &&
                        !"jpg".equalsIgnoreCase(suffix) &&
                        !"jpeg".equalsIgnoreCase(suffix)) {
                    return DataResponse.errorMsg("图片格式不正确！");
                }
                // 指定要上传的文件  本地上传  File localFile = new File("/Users/mac/Pictures/012.jpg");
                InputStream fileInputStream = file.getInputStream();
                // 指定要上传到的存储桶.
                String bucketName = fileUpload.getBucketName();
                // 指定要上传到 COS 上对象键.
                path = fileUpload.getObjectName() + "/" + userId + "/" + filename + ".jpg";
                ObjectMetadata objectMetadata = new ObjectMetadata();
                objectMetadata.setContentLength(file.getSize());//文件的大小.
                objectMetadata.setContentType(file.getContentType());//文件的类型.
                PutObjectRequest putObjectRequest = new PutObjectRequest(bucketName, path, fileInputStream, objectMetadata);
                cosClient.putObject(putObjectRequest);
                log.info("上传全路径 :{}", path);
            }
        } else {
            return DataResponse.errorMsg("文件不能为空(′⌒`)");
        }
        if (StringUtils.isNotBlank(path)) {
            //获取图片地址.
            String imageServerUrl = fileUpload.getBaseUrl();
            String finalUserFaceUrl = imageServerUrl + path;
            //更新用户头像到数据库.
            Users userResult = userService.updateUserFace(userId, finalUserFaceUrl);
            //增加令牌token，会整合进redis，分布式会话.
            UsersVo usersVo = conventUsersVo(userResult);
            CookieUtils.setCookie(request, response, "user", JSON.toJSONString(usersVo), true);
        } else {
            return DataResponse.errorMsg("上传头像失败(′⌒`)");
        }
        return BaseResponse.ok();
    }

    private UsersVo conventUsersVo(Users user) {
        String uniqueToken = UUID.randomUUID().toString().trim();
        redisService.setCacheObject(AppConstants.REDIS_USER_TOKEN + ":" + user.getId(), uniqueToken);
        UsersVo usersVo = UsersVo.Converter.INSTANCE.do2Vo(user);
        usersVo.setUserUniqueToken(uniqueToken);
        return usersVo;
    }

    // 处理校验消息
    private Map<String, String> getErrors(BindingResult bindingResult) {
        Map<String, String> map = new HashMap<>();
        List<FieldError> fieldErrors = bindingResult.getFieldErrors();
        fieldErrors.forEach(fieldError -> {
            String field = fieldError.getField();
            String defaultMessage = fieldError.getDefaultMessage();
            map.put(field, defaultMessage);
        });
        return map;
    }

    // 去除隐私值返回给前端.
    private void setNullProperty(Users userResult) {
        userResult.setPassword(null);
        userResult.setMobile(null);
        userResult.setEmail(null);
        userResult.setCreatedTime(null);
        userResult.setUpdatedTime(null);
        userResult.setBirthday(null);
    }
}
